package com.wushijia.highconcurrency.semaphore;

import static java.lang.Thread.currentThread;

import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo2 {

  public static void main(String[] args) {
    int packCar = 3;
    System.out.println("这里有" + packCar + "个停车位，先到先得");
    MySemaphore mySemaphore = new MySemaphore(packCar, true);

    Thread thread1 = new Thread(new ParkCar(1, "兰博基尼", mySemaphore), "赵四");
    Thread thread2 = new Thread(new ParkCar(2, "大G", mySemaphore), "刘能，谢广坤");
    Thread thread3 = new Thread(new ParkCar(1, "MINI", mySemaphore), "宋晓锋");

    thread1.start();
    thread2.start();
    thread3.start();
    //中断导致未成功获取信号的线程也能释放信号,可将获取信号异常单独包裹，catch异常后返回、或者使用自定义MySemaphore
    //thread2.interrupt();
  }

  private static class ParkCar implements Runnable {

    private final int permits;
    private final String car;
    private final MySemaphore mySemaphore;

    public ParkCar(int permits, String car, MySemaphore semaphore) {
      this.permits = permits;
      this.car = car;
      this.mySemaphore = semaphore;
    }

    @Override
    public void run() {
      if (mySemaphore.availablePermits() < permits) {
        System.out.println(currentThread().getName() + "来停车，车位不足，请等待！");
      }
      try {
        //获取许可
        mySemaphore.tryAcquire(permits);
        //可用许可，此处不可使用drainPermits（获取剩下所有的许可后返回获得了多少个许可，用尽剩余 许可）
        System.out.println(currentThread().getName() + "把他的" + car + "停下了，还剩余" + mySemaphore.availablePermits() + "个车位");

        int parkTime = ThreadLocalRandom.current().nextInt(1, 6);
        TimeUnit.SECONDS.sleep(parkTime);
      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        //释放许可
        mySemaphore.release(permits);
        System.out.println(currentThread().getName() + "把他的" + car + "开走了，还剩余" + mySemaphore.availablePermits() + "个车位");
      }
    }
  }
}
